<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        
        // 2. function
        Function.prototype.a = 1;
        Object.prototype.a = 2;
        function fn() { }
        let obj = new fn();
        console.log(obj.a);
        console.log(fn.a)
        console.dir(obj)


        // 3. new 的实现
        // new 的步骤
        // 1.在内存中创建一个空对象
        // 2.让this 指向这个新对象
        // 3.执行构造函数里面的代码，给这个对象添加属性和方法
        // 4.返回这个新对象（构造函数不需要return）
        function myNew(obj, ...args) {
            let myObj = Object.create(obj.prototype);  // new 返回的是一个obj
            let result = obj.call(myObj, ...args)
            // 正常规定,如何fn返回的是null或undefined(也就是不返回内容),我们返回的是obj,否则返回rel
            return result instanceof Object ? result : myObj
        }
        // 不借助object.create
        function _new(target) {
            if (typeof target !== "function")
                throw new TypeError("target must be a function");
            // 1. 创建一个全新的对象
            var obj = {}; // 相比较object.create(null) 上面会有 __proto__  指向Object 
            // 2. __proto__ 指向对象原型  
            obj.__proto__ = target.prototype;  // new 出来的实例 指向的是狗站函数的原型 也就是targe.prototype 
            // 3. 绑定上下文到 obj
            var result = target.apply(obj, Array.prototype.slice.call(arguments, 1));  // 给
            // 4.如果该函数没有返回对象，则返回新创建的对象
            var isObject = typeof result === "object" && result !== null;
            var isFunction = typeof result === "function";

            return isObject || isFunction ? result : obj;
        }

        Object.prototype.myCreate = function (obj) {
            let fn = function () { }
            fn.prototype = obj
            return new fn()
        }

        // 4. 就是看是否是基本类型，与对象类型
        console.log(new String(''), String(""), new String('') instanceof Object)
        // // true
        // (null) instanceof Object
        // ("1") instanceof Object
        // (String()) instanceof Object
        // // false
        // ({}) instanceof Object  

        // 5. object.create(null) 与 {} 的区别
        // ------------------------------------
        // 1）通过字面量的方式定义对象，其原型指向 Object.prototype，也就是 obj.__proto__ === Object.prototype，同时包含了toString,hasOwnProperty等方法。
        // 2）通过Object.create(null)创建出来的对象是一个干净对象，除自身属性之外，没有附加其他属性
        // https://blog.csdn.net/seafishyls/article/details/102472279?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.no_search_link


        // 5. 执行代码求输出，并说明为什么，严格模式下输出有变化吗，为什么
        var a = function () { this.b = 3; }
        var c = new a(); // new this 指向实例
        a.prototype.b = 9;
        var b = 7;
        a();  // this指向window

        console.log(b); // 3
        console.log(c.b); // c是实例 实例上有b 3
        
    </script>
</body>

</html>